可接元件並分享資料
只有function元件可使用,class元件不能使用
(1)function階層繼承 缺點:中間改變就斷掉了
(Lab_useContext > index_0.html)
function Me(props) {
return <h3>{props.secret}</h3>; // 3.在使用Father的方法取得資料
}
function Father(props) {
return <Me secret={props.secret} />; // 2.把GrandFather的secret給Me //4.回傳給GrandFather
// return (
// <h3>{props.secret}</h3>
// )
}
function GrandFather(props) {
let [secret, setSecret] = React.useState("work harder or work smarter"); // 1.secret設定為字串 setSecret=方法 //5.變更後顯示
return (
<React.Fragment>
<Father secret={secret} />
</React.Fragment>
);
}
(2)雖然Father不用收,但還是很麻煩==
(Lab_useContext > index_1.html)
function Me(props) {
// 3.Provider搭配Consumer並使用=>接資料
return (
<heirloom.Consumer>
{
secret =>
<h3>{secret}</h3>
}
</heirloom.Consumer>
);
}
function Father(props) {
return <Me /> // 2.回傳Me,不用接GrandFather
// return (
// <h3>{props.secret}</h3>
// )
}
function GrandFather(props) {
let [secret, setSecret] = React.useState("work harder or work smarter");
return (
// 1.GrandFather把傳家寶跟<Father />綁在一起,所以Father不用接
<React.Fragment>
<heirloom.Provider value={secret}>
<Father />
</heirloom.Provider>
</React.Fragment>
);
}
(3)使用 useContext取得資料,createContext限制只有哪些元件可取得
(Lab_useContext > index_2.html)
// useContext取得資料,createContext限制只有哪些元件可取得
// 1. React.createContext()只有在這個範圍內的元件,才能使用
var heirloom = React.createContext();
function Me(props) {
let secret = React.useContext(heirloom); // 4.useContext可以取得資料
return <h3>{secret}</h3>;
}
function Father(props) {
// 3.Father包含<Me />
return <Me />;
// return (
// <h3>{props.secret}</h3>
// )
}
function GrandFather(props) {
//回傳陣列 ; useState設定secret=字串,setSecret=ƒ()
let [secret, setSecret] = React.useState("work harder or work smarter");
let heirloomState = { secret, setSecret };
console.log(heirloomState);
return (
// 2.設定範圍 GrandFather包含<Father />
<React.Fragment>
<heirloom.Provider value={secret}>
<Father />
</heirloom.Provider>
</React.Fragment>
);
}
(4)最終版本:設定好可以使用的元件範圍,及可以使用的物件
// 1. React.createContext()只有在這個範圍內的元件,才能使用
var heirloom = React.createContext();
// 3.使用useContext就可取出傳家寶,取得secret, setSecret
function Me(props) {
let { secret, setSecret } = React.useContext(heirloom);
// 4.事件處理程序 拿secret, setSecret來用
let doTest = () => {
setSecret("Work smarter"); //把setSecret方法的倉庫拿來,使用
document.title = Date();
};
// 4.事件處理程序 拿secret, setSecret來用
return (
//把secret字串的倉庫拿來,使用
<div>
<h3>{secret}</h3>
<button onClick={doTest}>test</button>
</div>
);
}
function Father(props) {
// 3. Father包含<Me />
return <Me />;
// return (
// <h3>{props.secret}</h3>
// )
}
function GrandFather(props) {
// 回傳陣列 ; useState設定secret=字串,setSecret=ƒ()改變資料的方法
let [secret, setSecret] = React.useState("work harder or work smarter");
// heirloomState 建立成一個物件,讓Provider(傳家寶)的值={}
let heirloomState = { secret, setSecret };
return (
// 2. 設定範圍 GrandFather包含<Father /> 並設定傳家寶Provider
// heirloomState = { secret, setSecret }; 物件
<React.Fragment>
<heirloom.Provider value={heirloomState}>
<Father />
</heirloom.Provider>
</React.Fragment>
);
}
//useState回傳[],[]收下
let [secret, setSecret] = React.useState("work harder or work smarter");
//heirloomState是物件{}
let heirloomState = { secret, setSecret };
<React.Fragment>
<heirloom.Provider value={heirloomState}> //{}收下
<Father />
</heirloom.Provider>
</React.Fragment>
(Lab_useMemo > index_OK.html)
// 3.跑程式
function App(props) {
var [data1, setData1] = React.useState(1); //useState回傳[],只能用[]裝
var [data2, setData2] = React.useState(1);
var workResult = React.useMemo(() => {
//useMemo會記憶原本data1是甚麼
//此處只用data1
return longTimeWork(data1); //參數
}, [data1]); //資料 ; 4.判斷:當[data1]改變我才跑這個 return longTimeWork(data1) function,如果[data1]沒有改變就不會跑
let changeData1 = () => {
// 1.按按鈕 data1 +1
setData1(data1 + 1);
};
//按第二個按鈕不會執行workResult 節省效能
let changeData2 = () => {
setData2(data2 + 1);
}; C:\temp
// 2.執行return
return (
<React.Fragment>
<h3>
workResult: {workResult}, data1: {data1}, data2: {data2}
</h3>
<button class="btn btn-outline-success" onClick={changeData1}>
change data1
</button>
<button class="btn btn-outline-primary" onClick={changeData2}>
change data2
</button>
</React.Fragment>
);
(1)
Simple React Snippets 套件安裝 => 元件產生器
Snippets 簡寫
https://marketplace.visualstudio.com/items?itemName=burkeholland.simple-react-snippets
(2)Lab_counters > counter-app
create-react-app counter-app
建立資料夾counter-app
npm install bootstrap@4.1.1
counter-app資料夾內安裝bootstrap@4.1.1
npm start
跑package.json "start": "react-scripts start",
http://localhost:3000/
(3)Lab_counters > src > index.js
import App from './App'; //引用有物件的.js 需from
import 'bootstrap/dist/css/bootstrap.min.css'; //引用單純沒有物件的.js或.css 無須from
(4)Lab_counters > src > components > counter.jsx
imrc 快速建立引用
cc 快速建立類別
按tab跳行
import React, { Component } from 'react';
class Counter extends Component {
state = { }
render() {
return ( <h1>hello</h1> );
}
}
export default Counter;
(5)Lab_counters > src > index.js
改引用components/counter.jsx
import Counter from './components/counter.jsx';
ReactDOM.render(
// 測試看看有沒有引用到BS
<React.StrictMode>
<Counter />
<button className="btn btn-outline-success">OK</button>
</React.StrictMode>,
document.getElementById('root')
);
此時會顯示hello http://localhost:3000/
(6)Lab_counters > src > components > counter.jsx
使用方法formatCount()
formatCount(){
// 方法1.
// return this.state.count === 0? "Zero" : this.state.count ;
// 方法2. this.state做成物件
var {count} = this.state;
return count === 0? "Zero" : count ;
}
render() {
return (
<div>
<span>{this.formatCount()}</span><hr />
<button className="btn btn-outline-success">增加</button>
</div>
);
}
(7)增加圖片、樣式
state = {
count:0,
imgUrl: "https://dummyimage.com/200x200/000/fff"
}
//製作樣式物件 大寫必要font"W"eight(CSS內樣式)
styles = {
fontWeight:"bold",
fontSize:"3em",
fontStyle:"italic"
};
render() {
return (
<div>
//圖片
<img src= {this.state.imgUrl} /><hr />
//新增樣式
<span style={this.styles} className="badge badge-primary m-2">{this.formatCount()}</span><hr />
</div>
);
}
(8)製作判別式 並 設定套用不同樣式
styles = {
fontWeight:"bold",
fontSize:"3em",
fontStyle:"italic"
};
formatCount(){
// 方法1.
// return this.state.count === 0? "Zero" : this.state.count ;
// 方法2. this.state做成物件
var {count} = this.state;
return count === 0? "Zero" : count ;
}
//數值0=會變成黃色
getBadgeClasses() {
let myClassName = "badge m-2 ";
myClassName += (this.state.count === 0) ? "badge-warning" : "badge-primary";
return myClassName;
}
render() {
return (
<div>
{/* 設定藍色 */}
<span style={this.styles} className="badge badge-primary m-2">{this.formatCount()}</span><hr />
{/* render內,設定紅色 */}
<span style={this.styles} className={myClassName}>{this.formatCount()}</span><hr />
{/* getBadgeClasses(),設定黃色 */}
{/* styles + getBadgeClasses + formatCount 樣式在遇到0的時候會變成黃色 */}
<span style={this.styles} className={this.getBadgeClasses()}>{this.formatCount()}</span><hr />
</div>
);
}
(9)製作tage項目[]
class Counter extends Component {
state = {
imgUrl: "https://dummyimage.com/200x200/000/fff", //製作圖片物件
count:0,
tage : ["tage1","tage2","tage3"]
}
render() {
return (
<ul>
{/* tage有幾個就跑幾個 */}
{/* index.js:1 Warning: Each child in a list should have a unique "key" prop. */}
{/* 警告:要給tage唯一的key 所以幫li增加key */}
{this.state.tage.map(x=> <li key={x}>000</li>)}
{this.state.tage.map(x=> <li key={x}>{x}</li>)}
</ul>
</div>
);
}
(10)把tage項目製作成function方法顯示
class Counter extends Component {
state = {
imgUrl: "https://dummyimage.com/200x200/000/fff", //製作圖片物件
count:0,
tage : ["tage1","tage2","tage3"]
}
renderTags(){
if(this.state.tage.length > 0 ){
return <h3>我有東西唷!!請嘗試改變我~</h3>
}
return(
<ul>
{this.state.tage.map(x=> <li key={x}>{x}</li>)}
</ul>
);
}
render() {
return (
<div>
<ul>
{/* &&判斷方式,前面true才會判斷後面,並顯示後面 */}
{/* 實驗:把tage : ["tage1","tage2","tage3"]清空 */}
{this.state.tage.length == 0 && "請建立一個清單"} <br />
{this.renderTags()}
</ul>
</div>
);
}
複製過的東西會貼在上面
截圖會被放到 C:\temp
可以,npm i jquery 要安裝
import 'jquery/dist/jquery';